package com.yyge.config.security.login;

import com.yyge.config.Constants;
import com.yyge.config.security.dto.SecurityUser;
import com.yyge.config.security.service.impl.UserDetailsServiceImpl;
import com.yyge.mapper.LogMapper;
import com.yyge.mapper.UserMapper;
import com.yyge.utils.PasswordUtils;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import java.beans.Transient;
import java.util.Date;
import java.util.HashMap;

/**
 * <p> 自定义认证处理 </p>
 *
 * @author : gityyge
 * @description :
 * @date : 2019/10/12 14:49
 */
@Component
@Slf4j
public class AuthProvider implements AuthenticationProvider {

    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogMapper logMapper;

    /**
     * 登录鉴权
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    @Transient
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //System.out.printf("11");
        // 获取前端表单中输入后返回的用户名、密码
        String userName = (String) authentication.getPrincipal();
        String password = (String) authentication.getCredentials();

        SecurityUser userInfo = (SecurityUser) userDetailsService.loadUserByUsername(userName);
        // System.out.printf("333");
        boolean isValid = PasswordUtils.isValidPassword(password, userInfo.getPassword(), userInfo.getCurrentUserInfo().getSalt());
        // 验证密码
        if (!isValid) {
            log.error("密码错误！");
            throw new BadCredentialsException("密码错误！");
        }

        // 前后端分离情况下 处理逻辑...
        // 更新登录令牌
        //String token = PasswordUtils.encodePassword(String.valueOf(System.currentTimeMillis()), Constants.SALT);
        // 当前用户所拥有角色代码
        String roleCodes = userInfo.getRoleCodes();
        HashMap<String, Object> claims = new HashMap<>();
        claims.put("role",roleCodes);
        claims.put("userId",userInfo.getCurrentUserInfo().getId());
        claims.put("userName",userInfo.getCurrentUserInfo().getUsername());
        claims.put("nickName",userInfo.getCurrentUserInfo().getNickName());
        claims.put("sex",userInfo.getCurrentUserInfo().getSex());
        claims.put("avatar",userInfo.getCurrentUserInfo().getAvatar());

        // 生成jwt访问令牌
        String jwt = Jwts.builder()
                // 用户角色
                .setClaims(claims)
                //.claim("role",roleCodes)
                // 主题 - 存用户名
                .setSubject(authentication.getName())
                //.setPayload(token)
                // 过期时间 - 30分钟
                .setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000))
                // 加密算法和密钥
                .signWith(SignatureAlgorithm.HS512, Constants.SALT)
                .compact();
         //记录日志
        userInfo.getCurrentUserInfo().setToken(jwt);
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userInfo, password, userInfo.getAuthorities());
        return token;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
